home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / cenvid / copy.cmm < prev    next >
Encoding:
Text File  |  1995-10-11  |  15.3 KB  |  530 lines

  1. /*
  2.  * Copy.cmm
  3.  *
  4.  * A copy script for the CEnvi shell. It does what the DOS copy
  5.  * command does.
  6.  */
  7.  
  8. #include "Netware.lib"
  9.  
  10. usage()
  11. {
  12.   printf("Use the COPY command to copy one or more file(s) from one\n");
  13.   printf("location to another.\n");
  14.   printf("Syntax:\n");
  15.   printf("  COPY [drive][path] filename [+][,,][drive][path][filename] [/V]\n");
  16.   printf("where:\n");
  17.   printf("  drive/path/filename   Specifies the file to be copied.\n");
  18.   printf("  +                     Combines or appends files.\n");
  19.   printf("  + ,,                  Updates the time and date of a file.\n");
  20.   printf("  drive/path/filename   Specifies the target file name.\n");
  21.   printf("  /V                    Verifies that sectors written to the target\n");
  22.   printf("                        disk are recorded properly.\n");
  23.   exit(EXIT_FAILURE);
  24. }
  25.  
  26. /* ---------------------------------------------------------------------- */
  27.  
  28. /*
  29.  * Some DOS functions
  30.  */
  31. SetFileAttributes(pFileName,pAttributes)
  32. {
  33.    lReg.ah = 0x43;
  34.    lReg.al = 1;
  35.    lReg.cx = pAttributes;
  36.    if !defined(_DOS32_)
  37.       lReg.ds = segment(pFileName), lReg.dx = offset(pFileName);
  38.    else
  39.       lReg.dx = pointer(pFileName);
  40.    return interrupt(0x21,lReg);
  41. }
  42.  
  43. SetFileDateAndTime(pFileName,pTime)
  44. {
  45.    lSuccess = False;
  46.    // Open file to get a handle
  47.    lReg.ah = 0x3D;
  48.    lReg.al = 0x42;
  49.    if !defined(_DOS32_)
  50.       lReg.ds = segment(pFileName), lReg.dx = offset(pFileName);
  51.    else
  52.       lReg.dx = pointer(pFileName);
  53.    if ( interrupt(0x21,lReg,lRegout) ) {
  54.       lHandle = lRegout.ax;
  55.       // write date to file
  56.       undefine(lReg);
  57.       lReg.ah = 0x57;
  58.       lReg.al = 1;
  59.       lReg.bx = lHandle;
  60.       lTm = localtime(pTime);
  61.       lReg.cx = (lTm.tm_sec / 2)
  62.               | (lTm.tm_min << 5)
  63.               | (lTm.tm_hour << 11);
  64.       lReg.dx = lTm.tm_mday
  65.               | ((lTm.tm_mon+1) << 5)
  66.               | ((lTm.tm_year-80) << 9);
  67.       lSuccess = interrupt(0x21,lReg);
  68.       // close file
  69.       undefine(lReg);
  70.       lReg.ah = 0x3E;
  71.       lReg.bx = lHandle;
  72.       interrupt(0x21,lReg);
  73.    }
  74.    return lSuccess;
  75. }
  76.  
  77. DOSTimeFromCalendar(time)
  78. {
  79.   dos = DOSTimeStructFromCalendar(time);
  80.   return (dos.time<<16) | (dos.date);
  81. }
  82.  
  83. DOSTimeStructFromCalendar(time)
  84. {
  85.   tm = localtime(time);
  86.   dos.time = (tm.tm_sec/2) | (tm.tm_min<<5) | (tm.tm_hour<<11);
  87.   dos.date = tm.tm_mday | ((tm.tm_mon+1)<<5) | ((tm.tm_year-80)<<9);
  88.   return dos;
  89. }
  90.  
  91. GMDOSTimeStructFromCalendar(time)
  92. {
  93.   tm = gmtime(time);
  94.   dos.time = (tm.tm_sec/2) | (tm.tm_min<<5) | (tm.tm_hour<<11);
  95.   dos.date = tm.tm_mday | ((tm.tm_mon+1)<<5) | ((tm.tm_year-80)<<9);
  96.   return dos;
  97. }
  98.  
  99. #define GENERIC_WRITE 0x40000000
  100. #define FILE_SHARE_READ 0x01
  101. #define FILE_SHARE_WRITE 0x02
  102. #define OPEN_EXISTING 3
  103. #define INVALID_HANDLE_VALUE -1
  104.  
  105. /* ---------------------------------------------------------------------- */
  106.  
  107. verify = FALSE;
  108. source[0] = "";
  109. num_source = 0;
  110. target = "";
  111. doing_plus = FALSE;
  112. update_time = FALSE;
  113.  
  114. parse_command_line(argc,argv)
  115. {
  116.    for( i=1;i<argc;i++ )
  117.    {
  118.       if( argv[i][0]=='-' || argv[i][0]=='/' )
  119.       {
  120.          switch( toupper(argv[i][1]) )
  121.          {
  122.             default: usage();
  123.             case 'V': verify = TRUE; break;
  124.          }
  125.          continue;
  126.       }
  127.       if( argv[i][0]=='+' )
  128.       {
  129.          if( doing_plus ) {
  130.             printf("Already doing plus mode.\n");
  131.             exit(EXIT_FAILURE);
  132.          }
  133.          if( num_source==0 ) {
  134.               printf("You must specify a file, then you can use + to specify more.\n");
  135.               exit(EXIT_FAILURE);
  136.          }
  137.          doing_plus = TRUE;
  138.          if( argv[i][1] ) {
  139.             argv[i]++;
  140.             i--;
  141.          }
  142.          continue;
  143.       }
  144.       if( argv[i][0]==',' )
  145.       {
  146.          if( !doing_plus || argv[i][1]!=',' ) {
  147.             printf("To update a file's time, use \"+ ,,\".\n");
  148.             exit(EXIT_FAILURE);
  149.          }
  150.          update_time = TRUE;
  151.          doing_plus = FALSE;
  152.          continue;
  153.       }
  154.       // Have a filename
  155.       if( num_source==0 || doing_plus ) {
  156.          strcpy(source[num_source++],argv[i]);
  157.          doing_plus = FALSE;
  158.          continue;
  159.       }
  160.  
  161.       if( target[0]!='\0' ) {
  162.          printf("Too many target files specified.\n");
  163.          exit(EXIT_FAILURE);
  164.       }
  165.       strcpy(target,argv[i]);
  166.    }
  167.    if( doing_plus ) { printf("Extraneous plus.\n"); exit(EXIT_FAILURE); }
  168.    if( num_source==0 )
  169.      { printf("No source file specified.\n"); exit(EXIT_FAILURE); }
  170.    if( target[0]=='\0' ) target = ".";
  171. }
  172.  
  173. /*
  174.  * Copy a single file. When done, set the time to the old file's time
  175.  * stamps if update_time not set
  176.  */
  177. copy_file(source,target)
  178. {
  179.   strcpy(src,FullPath(source));
  180.   strcpy(tar,FullPath(target));
  181.  
  182.   if( !stricmp(src,tar) )
  183.     {
  184. // Same file!
  185.       if( update_time )
  186.         {
  187.           dir = Directory(target);
  188.           if( dir==NULL || GetArraySpan(dir)>0 )
  189.             {
  190.               printf("Copy_file: error, target should be a single file.\n");
  191.               return;
  192.             }
  193.  
  194.           curtime = time();
  195.           if( defined(_NWNLM_) )
  196.             {
  197.               tempcreate[0] = DOSTimeFromCalendar(curtime);
  198.               tempaccess[0] = DOSTimeFromCalendar(curtime);
  199.               tempdate[0] =   DOSTimeFromCalendar(curtime);
  200.               tempbackup[0] = DOSTimeFromCalendar(curtime);
  201.  
  202.               code = NLMLink("SetFileInfo", target, 0x06, dir[0].attrib,
  203.                      tempcreate,
  204.                      tempaccess,
  205.                      tempdate,
  206.                      tempbackup,
  207.                      dir[0].uid);
  208.               if( code )
  209.                 printf("\nError setting attributes for file %s\n",target);
  210.               return;
  211.             }
  212.           if( defined(_DOS_) || defined(_DOS32_) || defined(_WINDOWS_) )
  213.             {
  214.               SetFileDateAndTime(target,curtime);
  215.               return;
  216.             }
  217.           if( defined(_NTCON_) || defined(_NTWIN_) )
  218.             {
  219.               newbuf = ""; SetArraySpan(newbuf,100);
  220.  
  221.               if( (handle = DynamicLink("KERNEL32","CreateFileA",STDCALL,target,
  222.                                GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
  223.                                NULL,OPEN_EXISTING,0,NULL))
  224.                  !=INVALID_HANDLE_VALUE)
  225.                 {
  226.                   dos = GMDOSTimeStructFromCalendar(time());
  227.                   if( !DynamicLink("KERNEL32","DosDateTimeToFileTime",STDCALL,
  228.                                    dos.date,dos.time,newbuf) )
  229.                     {
  230.                       printf("Unable to convert to NT Time structure.\n");
  231.                       return;
  232.                     }
  233.  
  234.                   if( !DynamicLink("KERNEL32","SetFileTime",STDCALL,handle,newbuf,
  235.                                    newbuf,newbuf) )
  236.                     {
  237.                       err = DynamicLink("KERNEL32","GetLastError",STDCALL);
  238.                       printf("Unable to set new file time.\n",err);
  239.                     }
  240.  
  241.                   if( !DynamicLink("KERNEL32","CloseHandle",STDCALL,handle) )
  242.                     printf("Unable to close the handle.\n");
  243.                 } else {
  244.                   printf("Unable to open the file to touch it.\n");
  245.                 }
  246.               return;
  247.             }
  248.  
  249.           if( defined(_OS2_) )
  250.             {
  251.               printf("Cannot set timestamps on OS/2 yet.\n");
  252.               return;
  253.             }
  254.         }
  255.       printf("Cannot copy file to itself.\n");
  256.       return;
  257.     }
  258.  
  259.  
  260.   if( (fp = fopen(source,stricmp(source,"con")?"rb":"rt"))==NULL )
  261.     {
  262.       printf("Unable to open source file %s\n",source);
  263.       return;
  264.     }
  265.   if( (fp2 = fopen(target,stricmp(target,"con")?"wb":"rt"))==NULL )
  266.     {
  267.       printf("Unable to open target file %s\n",target);
  268.       fclose(fp);
  269.       return;
  270.     }
  271.  
  272.   buffer = ""; SetArraySpan(buffer,10000);
  273.  
  274.   while( 1 )
  275.     {
  276.       num = fread(buffer,9900,fp);
  277.       if( num<1 ) break;
  278.       fwrite(buffer,num,fp2);
  279.     }
  280.  
  281.   fclose(fp2);
  282.   fclose(fp);
  283.  
  284.   if( verify )
  285.     {
  286.       if( !stricmp(target,"con") || !stricmp(source,"con") )
  287.         {
  288.           printf("Cannot verify to or from the console.\n");
  289.           return;
  290.         }
  291.       if( (fp = fopen(source,"rb"))==NULL )
  292.         {
  293.           printf("Unable to open source file %s\n",source);
  294.           return;
  295.         }
  296.       if( (fp2 = fopen(target,"rb"))==NULL )
  297.         {
  298.           printf("Unable to write target file %s; check path is correct\n",target);
  299.           fclose(fp);
  300.           return;
  301.         }
  302.  
  303.       buffer2 = ""; SetArraySpan(buffer2,10000);
  304.  
  305.       while( 1 )
  306.         {
  307.           num = fread(buffer,9900,fp);
  308.           if( num<1 ) break;
  309.           num2 = fread(buffer2,9900,fp2);
  310.           if( num!=num2 || memcmp(buffer,buffer2,num) )
  311.             {
  312.               printf("File \"%s\" was copied incorrectly.\n",target);
  313.             }
  314.         }
  315.  
  316.       fclose(fp2);
  317.       fclose(fp);
  318.     }
  319.  
  320.   if( !update_time && stricmp(target,"con") )
  321.     {
  322.       dir = Directory(source);
  323.       if( dir==NULL || GetArraySpan(dir)!=0 )
  324.         {
  325.           printf("Error, can no longer open source file!\n");
  326.           return;
  327.         }
  328.  
  329.       if( defined(_NWNLM_) )
  330.         {
  331.           tempcreate[0] = DOSTimeFromCalendar(dir[0].Create);
  332.           tempaccess[0] = DOSTimeFromCalendar(dir[0].Access);
  333.           tempdate[0] =   DOSTimeFromCalendar(dir[0].Write);
  334.           tempbackup[0] = DOSTimeFromCalendar(dir[0].Backup);
  335.  
  336.           code = NLMLink("SetFileInfo",
  337.                      target,
  338.                      0x06,
  339.                      dir[0].attrib,
  340.                      tempcreate,
  341.                      tempaccess,
  342.                      tempdate,
  343.                      tempbackup,
  344.                      dir[0].uid);
  345.           if( code )
  346.             printf("\nError setting attributes for file %s\n",target);
  347.         }
  348.       if( defined(_DOS_) || defined(_DOS32_) || defined(_WINDOWS_) )
  349.         {
  350.           SetFileDateAndTime(target,dir[0].Create);
  351.           SetFileAttributes(target,dir[0].attrib);
  352.         }
  353.       if( defined(_NTCON_) || defined(_NTWIN_) )
  354.         {
  355.           DynamicLink("KERNEL32","SetFileAttributesA",STDCALL,target,dir[0].attrib);
  356.  
  357.           FTimeDef.LowTime = UWORD32;
  358.           FTimeDef.HightTime = UWORD32;
  359.  
  360.           if( (handle = DynamicLink("KERNEL32","CreateFileA",STDCALL,target,
  361.                                     GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
  362.                                     NULL,OPEN_EXISTING,0,NULL))
  363.              !=INVALID_HANDLE_VALUE)
  364.             {
  365.               dos = GMDOSTimeStructFromCalendar(dir[0].Create);
  366.               DynamicLink("KERNEL32","DosDateTimeToFileTime",STDCALL,
  367.                           dos.date,dos.time,FTimeDef,CreateFTime);
  368.               dos = GMDOSTimeStructFromCalendar(dir[0].Access);
  369.               DynamicLink("KERNEL32","DosDateTimeToFileTime",STDCALL,
  370.                           dos.date,dos.time,FTimeDef,AccessFTime);
  371.               dos = GMDOSTimeStructFromCalendar(dir[0].Write);
  372.               DynamicLink("KERNEL32","DosDateTimeToFileTime",STDCALL,
  373.                           dos.date,dos.time,FTimeDef,WriteFTime);
  374.  
  375.               if( !DynamicLink("KERNEL32","SetFileTime",STDCALL,handle,FTimeDef,CreateFTime,
  376.                                FTimeDef,AccessFTime,FTimeDef,WriteFTime) )
  377.                 {
  378.                   err = DynamicLink("KERNEL32","GetLastError",STDCALL);
  379.                   printf("Unable to set new file time.\n",err);
  380.                 }
  381.  
  382.                   if( !DynamicLink("KERNEL32","CloseHandle",STDCALL,handle) )
  383.                     printf("Unable to close the handle.\n");
  384.                 } else {
  385.                   printf("Unable to open the file to touch it.\n");
  386.                 }
  387.               return;
  388.         }
  389.  
  390.       if( defined(_OS2_) )
  391.         {
  392.           printf("Cannot set time on OS/2 yet.\n");
  393.           exit(EXIT_FAILURE);
  394.         }
  395.     }
  396. }
  397.  
  398. copy_multiple(target)
  399. {
  400.   if( (fp2 = fopen(target,"w"))==NULL )
  401.     {
  402.       printf("Unable to write target file %s; check path is correct.\n",target);
  403.       return;
  404.     }
  405.  
  406.   buffer = ""; SetArraySpan(buffer,1024);
  407.   for( i=0;i<num_source;i++ )
  408.     {
  409.       files = Directory(source[i]);
  410.       for( j=0;files && j<=GetArraySpan(files);j++ )
  411.         {
  412.           if( (fp = fopen(files[j].name,"r"))==NULL )
  413.             {
  414.               printf("Unable to open source file %s\n",source);
  415.               fclose(fp2);
  416.               return;
  417.             }
  418.           do
  419.             {
  420.               num = fread(buffer,1024,fp);
  421.               if( num<1 ) break;
  422.               fwrite(buffer,num,fp2);
  423.             }
  424.           while( !feof(fp) );
  425.           fclose(fp);
  426.         }
  427.     }
  428.  
  429.   fclose(fp2);
  430. }
  431.  
  432. /*---------------------------------------------------------------------------*/
  433.  
  434. get_filename(source)
  435. {
  436.   filestruct = SplitFileName(source);
  437.   sprintf(newdir,"%s%s",filestruct.name,filestruct.ext);
  438.   return newdir;
  439. }
  440.  
  441.  
  442. main(argc,argv)
  443. {
  444.   if( defined(_OS2_) )
  445.     {
  446.       printf("This script does not yet support OS/2.\n");
  447.       exit(EXIT_FAILURE);
  448.     }
  449.  
  450.   parse_command_line(argc,argv);
  451.  
  452.   tar_dir = 0;
  453.   if( !strcmp(target,".") )
  454.     {
  455.       if( defined(_NWNLM_) )
  456.         strcat(target,"/");
  457.       else
  458.         strcat(target,"\\");
  459.       tarfiles = NULL;
  460.     } else tarfiles = Directory(target);
  461.  
  462.   if( tarfiles==NULL )
  463.     {
  464.       if( !strcmp(target,".\\") ) tar_dir = 1;
  465.       if( isalpha(target[0]) && target[1]==':' &&
  466.          (target[2]=='\0' ||
  467.           ((target[2]=='/' || target[2]=='\\') && target[3]=='\0') ) )
  468.         tar_dir = 1;
  469.     } else {
  470.       if( GetArraySpan(tarfiles)>0 )
  471.         {
  472. // This is the case where the user typed something like : copy *.txt *.bak
  473.           printf("Cannot copy file(s) to multiple destinations.\n");
  474.           exit(EXIT_FAILURE);
  475.         }
  476.       strcpy(target,tarfiles[0].name);
  477.       if( tarfiles[0].attrib & _A_SUBDIR )
  478.         {
  479.           tar_dir = 1;
  480.           strcat(target,"\\");
  481.         }
  482.     }
  483.  
  484.   if( num_source==1 )
  485.     {
  486.       files = Directory(source[0]);
  487.       if( files==NULL )
  488.         {
  489.           printf("No such file or directory.\n");
  490.           exit(EXIT_FAILURE);
  491.         }
  492. // If multiple file move, the target must be a directory, otherwise just copy
  493. // the old file to the new one.
  494.       if( GetArraySpan(files)>0 )
  495.         {
  496.           if( !tar_dir )
  497.             {
  498.               copy_multiple(target); exit(EXIT_SUCCESS);
  499.             }
  500.  
  501.           for( i=0;i<=GetArraySpan(files);i++ )
  502.             {
  503.               if( (files[i].attrib & _A_SUBDIR)==0 )
  504.                 {
  505.                   strcpy(tmp,target);
  506.                   strcat(tmp,get_filename(files[i].name));
  507.                   copy_file(files[i].name,tmp);
  508.                 }
  509.             }
  510.         } else {
  511.           if( tar_dir )
  512.             {
  513.               sprintf(tmp,"%s%s",target,get_filename(files[0].name));
  514.             } else {
  515.               strcpy(tmp,target);
  516.             }
  517.           copy_file(files[0].name,tmp);
  518.         }
  519.     } else {
  520. // In this case, we copy multiple files into a single file, concatenating them
  521.       if( tar_dir )
  522.         {
  523.           sprintf(tmp,"%s%s",target,get_filename(files[0].name));
  524.         } else {
  525.           strcpy(tmp,target);
  526.         }
  527.       copy_multiple(tmp);
  528.     }
  529. }
  530.